/*
 * Created by JFormDesigner on Tue May 13 09:24:35 CST 2025
 */

package com.zjj.bams.server;

import com.zjj.bams.service.Bank;
import com.zjj.bams.utils.ThreadPoolUtils;

import java.awt.*;
import java.awt.event.*;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CyclicBarrier;
import javax.swing.*;

/**
 * @author zhoujunjie
 * @desc TODO
 * @date
 */
public class ServerPanel extends JPanel {

    //网络编程资源
    ServerSocket ss;
    Socket s;

    //线程池
    ThreadPoolUtils pool;
    //银行资源
    Bank bank;
    //线程安全的集合容器，存储所有接入客户端的Socket
    CopyOnWriteArrayList<Socket> clients;

    //标识 控制是否等待接入客户端
    boolean accept = false;

    public ServerPanel() {
        bank = Bank.getInstance();
        pool = new ThreadPoolUtils(40 , 3000);
        clients = new CopyOnWriteArrayList<>();

        initComponents();
    }

    //点击启动按钮
    private void start(ActionEvent e) {
        //计数器   当计数器累加至1，则开始执行任务
        CyclicBarrier barrier = new CyclicBarrier(1 , ()->startWork());

        if(ss==null){
            pool.exec(() ->{

                try {
                    //启动服务器
                    ss = new ServerSocket(8899);
                    JOptionPane.showMessageDialog(this, "服务器开启");

                    //设置按钮状态
                    startButton.setEnabled(false);
                    closeButton.setEnabled(true);

                    //设置允许接入客户端
                    accept = true;

                    //计数器 +1
                    barrier.await();
                } catch (IOException | InterruptedException | BrokenBarrierException ex) {
                    throw new RuntimeException(ex);
                }

            });
        }else{
            JOptionPane.showMessageDialog(this, "服务器已启动！");
        }
    }

    //开始执行任务  一旦计数器+1，达到循环屏障的条件，则会执行ss.accept()接入客户端的Socket，分配ServerTasker
    private void startWork(){
        //通过accept开关控制，是否无限接入客户端
        while (accept){
            try {
                //等待接入客户端
                s = ss.accept();
                System.out.println("客户端成功接入~");

                //添加客户端，为其分配一位“业务员”并分配任务
                if(s!=null && clients!=null){
                    clients.add(s);
                    //让线程池执行ServerTasker任务
                    ServerTasker tasker = new ServerTasker(bank , s);
                    pool.exec(tasker);
                }
            } catch (SocketException e) {
                JOptionPane.showMessageDialog(this, "服务器已关闭！");
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }

    //点击关闭按钮
    private void close(ActionEvent e) {
        if(ss==null){
            JOptionPane.showMessageDialog(this, "服务器未开启！");
            return;
        }

        //服务器开启状态，且未被关闭
        if(ss!=null && !ss.isClosed()){
            //---------------------释放客户端的资源---------------------
            //迭代clients客户端，将其socket一一关闭
            if(clients!=null && clients.size()>0){
                clients.forEach(socket -> {
                    if(socket!=null){
                        try {
                            socket.close();
                        } catch (IOException ex) {
                            throw new RuntimeException(ex);
                        }
                    }
                });
            }
            //清空集合
            clients.clear();

            //设置按钮状态
            startButton.setEnabled(true);
            closeButton.setEnabled(false);

            //改变无限接入客户端的标识,设置false表示不再接入客户端
            accept = false;

            //---------------------释放服务器资源---------------------
            try {
                ss.close();
                ss = null;
            } catch (IOException ex) {
                JOptionPane.showMessageDialog(this, "服务器未正确关闭！");
            }
        }else{
            JOptionPane.showMessageDialog(this, "服务器已关闭！");
        }
    }

    //跳转至RankPanel界面
    private void skipRank(ActionEvent e) {
        CardLayout card = (CardLayout)this.getParent().getLayout();
        card.show(this.getParent() , "rank");
    }

    private void initComponents() {
        // JFormDesigner - Component initialization - DO NOT MODIFY  //GEN-BEGIN:initComponents  @formatter:off
        titleLabel = new JLabel();
        startButton = new JButton();
        closeButton = new JButton();
        skipRankButton = new JButton();

        //======== this ========
        setLayout(null);

        //---- titleLabel ----
        titleLabel.setText("\u670d   \u52a1   \u5668");
        titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
        titleLabel.setFont(new Font("Microsoft YaHei UI", Font.BOLD, 28));
        add(titleLabel);
        titleLabel.setBounds(150, 65, 185, 45);

        //---- startButton ----
        startButton.setText("\u542f\u52a8");
        startButton.addActionListener(e -> start(e));
        add(startButton);
        startButton.setBounds(110, 185, 95, 35);

        //---- closeButton ----
        closeButton.setText("\u5173\u95ed");
        closeButton.addActionListener(e -> close(e));
        add(closeButton);
        closeButton.setBounds(305, 185, 95, 35);

        //---- skipRankButton ----
        skipRankButton.setText("\u5f00\u542f\u4e0a\u5e1d\u89c6\u89d2");
        skipRankButton.addActionListener(e -> skipRank(e));
        add(skipRankButton);
        skipRankButton.setBounds(175, 255, 160, 35);

        setPreferredSize(new Dimension(500, 365));
        // JFormDesigner - End of component initialization  //GEN-END:initComponents  @formatter:on
    }

    // JFormDesigner - Variables declaration - DO NOT MODIFY  //GEN-BEGIN:variables  @formatter:off
    private JLabel titleLabel;
    private JButton startButton;
    private JButton closeButton;
    private JButton skipRankButton;
    // JFormDesigner - End of variables declaration  //GEN-END:variables  @formatter:on
}
